﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SocketPostData.BLL;
using SocketPostData.DAL;
using SocketPostData.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SocketPostData
{
    //声明委托
    public delegate void SetDataDelegate(string message);

    public partial class Form1 : Form
    {
        System.Windows.Forms.Timer timer1;

        private Socket m_clientSocket;
        public SetDataDelegate onGetReceive;

        public Form1()
        {
            InitializeComponent();
            Init();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            System.Configuration.Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            this.txtIPAddress.Text = configuration.AppSettings.Settings["databaseIp"].Value;
            this.txtPort.Text = configuration.AppSettings.Settings["databasePort"].Value;
            this.onGetReceive += new SetDataDelegate(this.showMessage);

        }

        /// <summary>
        /// 获取市平台同步设备与参数列表
        /// </summary>
        /// <returns></returns>
        public List<sbgk_sjtbpzb> GetDataList()
        {
            List<sbgk_sjtbpzb> cache = CacheHelper.GetCache<sbgk_sjtbpzb>("argCacheKey");
            if (ReferenceEquals(cache, null))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetSyncDataList();
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argCacheKey", cache, timeout);
                }
                else
                {
                    this.showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":未获上传配置信息，上传失败");
                }
            }
            if ((cache != null) && (cache.Count == 0))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetSyncDataList();
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argCacheKey", cache, timeout);
                }
                else
                {
                    this.showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":未获上传配置信息，上传失败");
                }
            }
            return cache;
        }

        /// <summary>
        /// 获取市平台同步设备与参数列表
        /// </summary>
        /// <returns></returns>
        public List<sbgk_sjtbpzxxb> GetDcsArgInfoList()
        {
            List<sbgk_sjtbpzxxb> cache = CacheHelper.GetCache<sbgk_sjtbpzxxb>("argInfoCacheKey");
            if (ReferenceEquals(cache, null))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetDcsArgInfoList();
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argInfoCacheKey", cache, timeout);
                }
            }
            if ((cache != null) && (cache.Count == 0))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetDcsArgInfoList();
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argInfoCacheKey", cache, timeout);
                }
            }
            return cache;
        }

        /// <summary>
        /// 获取市平台同步设备与参数列表
        /// </summary>
        /// <returns></returns>
        public List<sbgk_sbcsxxb> GetArgSecondList()
        {
            List<sbgk_sbcsxxb> cache = CacheHelper.GetCache<sbgk_sbcsxxb>("argSecondCacheKey");
            if (ReferenceEquals(cache, null))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetEquipmentArgList(true);
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argSecondCacheKey", cache, timeout);
                }
            }
            else if ((cache != null) && (cache.Count == 0))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetEquipmentArgList(true);
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argSecondCacheKey", cache, timeout);
                }
            }
            return cache;
        }

        /// <summary>
        /// 获取市平台同步设备与参数列表
        /// </summary>
        /// <returns></returns>
        public List<sbgk_sjtbpzb_sum> GetDcsSumArgList()
        {
            List<sbgk_sjtbpzb_sum> cache = CacheHelper.GetCache<sbgk_sjtbpzb_sum>("argSumCacheKey");
            if (ReferenceEquals(cache, null))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetDcsSumArgList();
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argSumCacheKey", cache, timeout);
                }
            }
            else if ((cache != null) && (cache.Count == 0))
            {
                TimeSpan timeout = (TimeSpan)(DateTime.Now.AddDays(10) - DateTime.Now);
                cache = DBHelper.GetDcsSumArgList();
                if (cache.Count > 0)
                {
                    CacheHelper.SetCache("argSumCacheKey", cache, timeout);
                }
            }
            return cache;
        }

        /// <summary>
        /// 初始化推送任务
        /// </summary>
        public async void InitSyncTask(object source, EventArgs e)
        {
            try
            {
                List<sbgk_sjtbpzb> argList = GetDataList();  //参数列表
                List<sbgk_sjtbpzxxb> xxbList = GetDcsArgInfoList();  //获取冗余参数列表
                List<sbgk_sbcsxxb> secondArgList = GetArgSecondList();  //秒级数据列表
                List<sbgk_sjtbpzb_sum> sumArgList = GetDcsSumArgList();  //获取合并数据参数

                //检查连接状态
                if (m_clientSocket == null)
                {
                    m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                }
                if (!m_clientSocket.Connected)
                {
                    m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    ConnectServer();
                }

                var result = await SyncEquipmentWorkingData(argList, xxbList, secondArgList, sumArgList);

            }
            catch (Exception ex)
            {
                NLogger.Error(ex.Message + ex.StackTrace);
                timer1.Start();
                showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":" + ex.Message + Environment.NewLine + ex.Source + ex.StackTrace);
            }
        }

        /// <summary>
        /// 获取冗余字段数据
        /// </summary>
        /// <param name="siteDataList"></param>
        /// <param name="dcsDataList"></param>
        /// <param name="pzxxbList"></param>
        /// <returns></returns>
        public string GetDcsArgInfoStr(List<realwastegasdata> siteDataList, List<real_sbgk_sjjgb> dcsDataList, List<sbgk_sjtbpzxxb> pzxxbList)
        {
            var index = 2;  //编号从02开始

            var typeSiteData = typeof(realwastegasdata);
            var typeDcsData = typeof(real_sbgk_sjjgb);

            string content = "";
            foreach (var arg in pzxxbList)
            {
                if (string.IsNullOrEmpty(arg.sjtbpzb_dyzdmc))
                {
                    continue;
                }
                if (arg.sjtbpzb_dysjb == "real_sbgk_sjjgb")  //参数属于DCS
                {
                    var queryData = dcsDataList.FirstOrDefault(x => x.sbxxb_id == arg.sjtbpzb_dysjbid);

                    if (queryData != null)
                    {
                        decimal dvalue;
                        object rowValue = typeDcsData.GetProperty(arg.sjtbpzb_dyzdmc.ToLower()).GetValue(queryData, null);
                        bool parsesucc = decimal.TryParse(rowValue?.ToString() ?? "", out dvalue);   //转换是否成功

                        if (parsesucc)
                        {
                            if (arg.sjtbpzxxb_hsxs != 1)
                            {
                                dvalue = dvalue * arg.sjtbpzxxb_hsxs;
                            }
                            if (index < 10)
                            {
                                content += $@"{arg.sjtbpzb_csbm}_0{index}-Avg={decimal.Round(dvalue, 2)};";
                            }
                            else
                            {
                                content += $@"{arg.sjtbpzb_csbm}_{index}-Avg={decimal.Round(dvalue, 2)};";
                            }
                        }
                    }
                }
                if (arg.sjtbpzb_dysjb == "realwastegasdata")  //参数属于在线监测
                {
                    var queryData = siteDataList.FirstOrDefault(x => x.siteid == arg.sjtbpzb_dysjbid);

                    if (queryData != null)
                    {
                        decimal dvalue;
                        object rowValue = typeSiteData.GetProperty(arg.sjtbpzb_dyzdmc.ToLower()).GetValue(queryData, null);
                        bool parsesucc = decimal.TryParse(rowValue?.ToString() ?? "", out dvalue);   //转换是否成功

                        if (parsesucc)
                        {
                            if (arg.sjtbpzxxb_hsxs != 1)
                            {
                                dvalue = dvalue * arg.sjtbpzxxb_hsxs;
                            }
                            if (index < 10)
                            {
                                content += $@"{arg.sjtbpzb_csbm}_0{index}-Avg={decimal.Round(dvalue, 2)};";
                            }
                            else
                            {
                                content += $@"{arg.sjtbpzb_csbm}_{index}-Avg={decimal.Round(dvalue, 2)};";
                            }
                        }
                    }
                }

                index += 1;
            }

            return content;
        }

        /// <summary>
        /// 开始同步数据
        /// </summary>
        /// <param name="argList">设备参数列表</param>
        /// <param name="pzxxbList">冗余参数列表</param>
        /// <param name="secondArgList">二级系统参数列表</param>
        /// <param name="sumArgList">数据求和参数列表</param>
        /// <returns></returns>
        public async Task<bool> SyncEquipmentWorkingData(List<sbgk_sjtbpzb> argList,List<sbgk_sjtbpzxxb> pzxxbList,List<sbgk_sbcsxxb> secondArgList, List<sbgk_sjtbpzb_sum> sumArgList)
        {
            //获取DCS和在线监测实时数据
            List<realwastegasdata> siteDataList = DBHelper.GetRealSiteDataList();
            List<real_sbgk_sjjgb> dcsDataList = DBHelper.GetRealDcsDataList();
            List<real_dcs_sjjgbsecond> secondDataList = DBHelper.GetPreMinSecondData_Max();
            List<real_islandsumdata> islandDataList = DBHelper.GetRealIslandDataList();

            //数据分组
            var distinct = argList.GroupBy(x => new
            {
                x.sjtbpzb_sbid,
                x.sjtbpzb_sbmc,
                x.sjtbpzb_gyqy,
                x.sjtbpzb_mnnumber,
                x.sjtbpzb_pwnumber
            }).Select(x => new
            {
                x.Key.sjtbpzb_sbid,
                x.Key.sjtbpzb_sbmc,
                x.Key.sjtbpzb_gyqy,
                x.Key.sjtbpzb_mnnumber,
                x.Key.sjtbpzb_pwnumber
            }).ToList();

            string timestamp = DateTime.Now.ToString("yyyyMMddHHmm")+"00000";
            string dateTime = DateTime.Now.ToString("yyyyMMddHHmm")+"00";

            var typeSiteData = typeof(realwastegasdata);
            var typeDcsData = typeof(real_sbgk_sjjgb);

            foreach (var item in distinct)
            {
                if (string.IsNullOrEmpty(item.sjtbpzb_mnnumber) || string.IsNullOrEmpty(item.sjtbpzb_pwnumber))
                {
                    continue;
                }

                bool hasData = false;

                string content = $@"QN={timestamp};ST=51;CN=2051;PW={item.sjtbpzb_pwnumber};MN={item.sjtbpzb_mnnumber};Flag=5;CP=&&DataTime={dateTime};";

                var queryArgs = argList.Where(x => x.sjtbpzb_sbid == item.sjtbpzb_sbid).ToList();   //设备参数列表

                foreach (var arg in queryArgs)
                {
                    if (string.IsNullOrEmpty(arg.sjtbpzb_dyzdmc))
                    {
                        continue;
                    }

                    #region 参数属于DCS

                    if (arg.sjtbpzb_dysjb == "real_sbgk_sjjgb")
                    {
                        decimal dvalue;

                        var secondArgModel = secondArgList.FirstOrDefault(x => x.sbxxb_id == arg.sjtbpzb_dysjbid && x.sbcsxxb_zdmc == arg.sjtbpzb_dyzdmc);

                        if(secondArgModel !=null)   //秒级数据分钟最大值上传
                        {
                            var secondDataModel = secondDataList.FirstOrDefault(x => x.sbcsxxb_csdm == secondArgModel.sbcsxxb_csdm);

                            if(secondDataModel != null)
                            {
                                dvalue = (decimal)(secondDataModel.svalue ?? 0);
                                if(arg.sjtbpzb_hsxs != 1)
                                {
                                    dvalue = dvalue * arg.sjtbpzb_hsxs;
                                }
                                content += $@"{arg.sjtbpzb_csbm}-Avg={decimal.Round(dvalue, 2)};";
                                hasData = true;
                            }
                        }
                        else
                        {
                            var queryData = dcsDataList.FirstOrDefault(x => x.sbxxb_id == arg.sjtbpzb_dysjbid);

                            if (queryData != null)
                            {
                                object rowValue = typeDcsData.GetProperty(arg.sjtbpzb_dyzdmc.ToLower()).GetValue(queryData, null);
                                bool parsesucc = decimal.TryParse(rowValue?.ToString() ?? "", out dvalue);   //转换是否成功

                                if (parsesucc)
                                {
                                    if (arg.sjtbpzb_hsxs != 1)
                                    {
                                        dvalue = dvalue * arg.sjtbpzb_hsxs;
                                    }

                                    content += $@"{arg.sjtbpzb_csbm}-Avg={decimal.Round(dvalue, 2)};";
                                    hasData = true;
                                }
                            }
                        }
                    }

                    #endregion

                    #region 参数属于在线监测

                    if (arg.sjtbpzb_dysjb == "realwastegasdata")
                    {
                        var queryData = siteDataList.FirstOrDefault(x => x.siteid == arg.sjtbpzb_dysjbid);

                        if (queryData != null)
                        {
                            decimal dvalue;
                            object rowValue = typeSiteData.GetProperty(arg.sjtbpzb_dyzdmc.ToLower()).GetValue(queryData, null);
                            bool parsesucc = decimal.TryParse(rowValue?.ToString() ?? "", out dvalue);   //转换是否成功

                            if (parsesucc)
                            {
                                if (arg.sjtbpzb_hsxs != 1)
                                {
                                    dvalue = dvalue * arg.sjtbpzb_hsxs;
                                }
                                content += $@"{arg.sjtbpzb_csbm}-Avg={decimal.Round(dvalue, 2)};";
                                hasData = true;
                            }
                        }
                    }

                    #endregion

                    #region 参数属于DCS合并监测

                    if (arg.sjtbpzb_dysjb == "dcs_sum_data")  //
                    {
                        var querySumArgs = sumArgList.Where(x => x.sjtbpzb_id == arg.id).ToList();
                        decimal sumdvalue = 0;

                        foreach (var sumArg in querySumArgs)
                        {
                            decimal dvalue;
                            var queryData = dcsDataList.FirstOrDefault(x => x.sbxxb_id == sumArg.sjtbpzb_dysjbid) ?? new real_sbgk_sjjgb();
                            object rowValue = typeDcsData.GetProperty(sumArg.sjtbpzb_dyzdmc.ToLower()).GetValue(queryData, null);
                            bool parsesucc = decimal.TryParse(rowValue?.ToString() ?? "", out dvalue);   //转换是否成功

                            if (parsesucc)
                            {
                                if (sumArg.sjtbpzb_hsxs != 1)
                                {
                                    dvalue = dvalue * sumArg.sjtbpzb_hsxs;
                                }
                                sumdvalue += dvalue;
                            }
                        }
                        if(arg.sjtbpzb_maxvalue != null)
                        {
                            if(sumdvalue > arg.sjtbpzb_maxvalue)
                            {
                                sumdvalue = (decimal)arg.sjtbpzb_maxvalue;
                            }
                        }

                        content += $@"{arg.sjtbpzb_csbm}-Avg={decimal.Round(sumdvalue, 2)};";
                        hasData = true;
                    }

                    #endregion

                    #region 参数属于孤岛累计数据

                    if (arg.sjtbpzb_dysjb == "real_islandsumdata")
                    {
                        var queryData = islandDataList.FirstOrDefault(x => x.sbxxb_id == arg.sjtbpzb_dysjbid);

                        if (queryData != null)
                        {
                            decimal dvalue;
                            
                            if (queryData.data_value !=null)
                            {
                                dvalue = (decimal)queryData.data_value;
                                if (arg.sjtbpzb_hsxs != 1)
                                {
                                    dvalue = dvalue * arg.sjtbpzb_hsxs;
                                }
                                content += $@"{arg.sjtbpzb_csbm}-Avg={decimal.Round(dvalue, 2)};";
                                hasData = true;
                            }
                        }
                    }

                    #endregion

                    //添加冗余字段
                    var queryInfoList = pzxxbList.Where(x => x.sjtbpzb_sbid == arg.sjtbpzb_sbid && x.sjtbpzb_csbm == arg.sjtbpzb_csbm).ToList();

                    var contentInfoStr = GetDcsArgInfoStr(siteDataList, dcsDataList, queryInfoList);

                    if (!string.IsNullOrEmpty(contentInfoStr))
                    {
                        content += contentInfoStr;
                    }
                }

                content = content.TrimEnd(';');
                content = content + "&&";

                string datalength = HJ212_2017.GetHj212DataLength(content);
                string dataCRC = HJ212_2017.GetHj212Crc16(content);

                string postData = $@"##{datalength}{content}{dataCRC}" + Environment.NewLine;

                if (!hasData)
                {
                    continue;
                }

                await Task.Run(() =>
                {
                    SendMessage(postData);

                    //if (item.sjtbpzb_sbid == 16)
                    //{
                    //    NLogger.Error(postData);
                    //}
                });
            }

            return true;
        }

        /// <summary>
        /// 启动点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.timer1 != null)
                {
                    this.timer1.Dispose();
                }
                CacheHelper.RemoveAllCache();
                this.Disconnect();
                if (m_clientSocket == null)
                {
                    m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                }
                if (!m_clientSocket.Connected)
                {
                    m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    ConnectServer();
                }
            }
            catch (Exception exception)
            {
                NLogger.Error(exception.Message + exception.StackTrace);
                string[] textArray1 = new string[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ":", exception.Message, Environment.NewLine, exception.Source, exception.StackTrace };
                this.showMessage(string.Concat(textArray1));
                Thread.Sleep(0xea60);
                this.btnStart_Click(null, null);
                return;
            }

            int num = 1;
            int.TryParse(ConfigurationManager.AppSettings["TimeInterval"], out num);
            timer1 = new System.Windows.Forms.Timer();
            timer1.Interval = 1000 * num;
            timer1.Tick += new EventHandler(InitSyncTask);//添加事件

            InitSyncTask(null, null);
            timer1.Start();
        }

        /// <summary>
        /// 停止事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            if (timer1 != null)
            {
                timer1.Dispose();
            }
            CacheHelper.RemoveAllCache();
            this.Disconnect();
            MessageBox.Show("停止成功!");
        }

        /// <summary>
        /// 测试连接事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTest_Click(object sender, EventArgs e)
        {
            if (ReferenceEquals(this.m_clientSocket, null))
            {
                this.m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.ConnectServer();
            }
            else if (this.m_clientSocket.Connected)
            {
                this.showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "服务器连接正常");
            }
            else
            {
                this.showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "服务器连接失败");
            }
        }

        private void showMessage(string message)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new SetDataDelegate(showMessage), message);
            }
            else
            {
                txtLog.Text = message + Environment.NewLine + txtLog.Text;
                //暂定1万字为限
                if (txtLog.Text.Length > 10000)
                {
                    txtLog.Text = txtLog.Text.Substring(0, 9000);
                }
            }
        }

        /// <summary>  
        /// 发送数据给服务器  
        /// </summary>  
        public void SendMessage(string data)
        {
            bool isconnect = this.m_clientSocket.Connected;
            if (isconnect)
            {
                byte[] bytes = Encoding.ASCII.GetBytes(data);
                this.m_clientSocket.Send(bytes);
            }
            else
            {
                showMessage(DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss") + "推送数据不成功，服务器未连接");
            }
        }

        /// <summary>
        /// 连接服务器
        /// </summary>
        public void ConnectServer()
        {
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(this.txtIPAddress.Text), int.Parse(this.txtPort.Text));
            m_clientSocket.Connect(remoteEP);
            showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "连接服务器成功");

            Thread thread = new Thread(RecieveMessage);
            thread.Start();
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            if ((this.m_clientSocket != null) && this.m_clientSocket.Connected)
            {
                this.m_clientSocket.Shutdown(SocketShutdown.Both);
                this.m_clientSocket.Close();
                this.m_clientSocket.Dispose();
            }
        }

        /// <summary>
        /// 返回消息
        /// </summary>
        private void RecieveMessage()
        {
            while (m_clientSocket.Connected)
            {
                try
                {
                    if (m_clientSocket.Available <= 0)
                    {
                        continue;
                    }
                    List<byte> list = new List<byte>();
                    byte[] buffer = new byte[0x400];
                    int num = 0;
                    while (true)
                    {
                        if (m_clientSocket.Available <= 0)
                        {
                            break;
                        }
                        num = m_clientSocket.Receive(buffer);
                        
                        if (num <= 0)
                        {
                            break;
                        }
                        int index = 0;
                        while (true)
                        {
                            if (index < num)
                            {
                                list.Add(buffer[index]);
                                index++;
                                continue;
                            }
                            if (num >= buffer.Length)
                            {
                                break;
                            }
                            break;
                        }
                    }
                    this.showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":" + Encoding.Default.GetString(list.ToArray()).Replace("\0", ""));
                    continue;
                }
                catch (Exception exception)
                {
                    NLogger.Error(exception.Message + exception.StackTrace);
                    this.showMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + exception.Message);
                }
            }
        }
    }
}
